﻿using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Globalization.DateTimeFormatting;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Color = Windows.UI.Color;
using Point = Windows.Foundation.Point;

namespace 纸片人
{
    public static class Function
    {
        static CanvasDevice device = CanvasDevice.GetSharedDevice();

        public async static Task<CanvasBitmap> SelectImage(string fileName)
        {
            FileOpenPicker picker = new FileOpenPicker();
            picker.FileTypeFilter.Add(".jpg");
            picker.FileTypeFilter.Add(".png");

            StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/123.jpg"));

            if (file == null)
                return null;

            CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(device, await file.OpenReadAsync());


            return bitmap;
        }

        public async static Task<CanvasBitmap> SelectImageAsync(CanvasDevice device = null)
        {
            if (device == null)
                device = CanvasDevice.GetSharedDevice();

            FileOpenPicker picker = new FileOpenPicker() { FileTypeFilter = { ".jpg", ".png" } };
            StorageFile file = await picker.PickSingleFileAsync();
            if (file == null)
                return null;
            CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(device, await file.OpenReadAsync());
            return bitmap;
        }

        public async static Task<CanvasBitmap> SelectImage(ICanvasResourceCreator de)
        {
            FileOpenPicker picker = new FileOpenPicker();
            picker.FileTypeFilter.Add(".jpg");
            picker.FileTypeFilter.Add(".png");

            StorageFile file = await picker.PickSingleFileAsync();

            if (file == null)
                return null;

            CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(de, await file.OpenReadAsync());


            return bitmap;
        }

        public async static Task SavePicture(CanvasRenderTarget canvasRenderTarget, IDictionary<string, IList<string>> fillTypeChoices, string suggestedFileName)
        {
            FileSavePicker save = new FileSavePicker()
            {
                SuggestedStartLocation = PickerLocationId.Desktop,
                SuggestedFileName = suggestedFileName
            };


            foreach (var item in fillTypeChoices)
                save.FileTypeChoices.Add(item);

            StorageFile file = await save.PickSaveFileAsync();
            if (file == null)
                return;
            CanvasBitmapFileFormat format = CanvasBitmapFileFormat.Jpeg;
            if (file.FileType == ".jpg")
                format = CanvasBitmapFileFormat.Jpeg;
            else if (file.FileType == ".png")
                format = CanvasBitmapFileFormat.Png;
            using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
                await canvasRenderTarget.SaveAsync(stream, format);

            MessageDialog md = new MessageDialog($"{file.Name}保存成功");
            await md.ShowAsync();
        }

        /// <summary>
        /// 初始化参数
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="colors"></param>
        /// <param name="tempColors"></param>
        /// <param name="image"></param>
        /// <param name="wb"></param>
        public static void InitialParameter(CanvasBitmap bitmap, out int width, out int height, out Color[] colors, out Color[] tempColors, Image image, out WriteableBitmap wb)
        {
            width = (int)bitmap.Size.Width;
            height = (int)bitmap.Size.Height;

            colors = bitmap.GetPixelColors();
            tempColors = new Color[colors.Length];
            wb = new WriteableBitmap(width, height);
            WriteableBitmap bi = new WriteableBitmap(width, height);

            bitmap.GetPixelBytes().CopyTo(bi.PixelBuffer);
            image.Source = bi;
        }


        /// <summary>
        /// 初始化参数
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="colors"></param>
        /// <param name="tempColors"></param>
        /// <param name="image"></param>
        /// <param name="wb"></param>
        public static void InitialParameter(CanvasBitmap bitmap, out int width, out int height, out Color[] colors, out Color[] tempColors)
        {
            width = (int)bitmap.Size.Width;
            height = (int)bitmap.Size.Height;

            colors = bitmap.GetPixelColors();
            tempColors = new Color[colors.Length];

        }


        /// <summary>
        /// 初始化图片
        /// </summary>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="image"></param>
        public static void InitialImage(byte[] colors, int width, int height, Image image, WriteableBitmap wb)
        {

            using (var b = CanvasBitmap.CreateFromBytes(device, colors, width, height, Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized))
            {
                byte[] currentByte = b.GetPixelBytes();
                currentByte.CopyTo(wb.PixelBuffer);
                wb.Invalidate();
                image.Source = wb;
                b.Dispose();
            }
        }

        /// <summary>
        /// 初始化图片
        /// </summary>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="image"></param>
        public static void InitialImage(CanvasBitmap bitmap, out int width, out int height, out Color[] colors)
        {
            width = (int)bitmap.Size.Width;
            height = (int)bitmap.Size.Height;
            colors = bitmap.GetPixelColors();
        }


        /// <summary>
        /// 初始化图片
        /// </summary>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="image"></param>
        public static void InitialImage(Color[] colors, int width, int height, Image image)
        {
            WriteableBitmap wb = new WriteableBitmap(width, height);
            using (var b = CanvasBitmap.CreateFromColors(device, colors, width, height))
            {
                byte[] currentByte = b.GetPixelBytes();
                currentByte.CopyTo(wb.PixelBuffer);

                image.Source = wb;
                b.Dispose();
            }
        }
        /// <summary>
        /// 初始化图片
        /// </summary>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="image"></param>
        /// <param name="wb"></param>
        public static void InitialImage(Color[] colors, int width, int height, Image image, WriteableBitmap wb)
        {


            using (var b = CanvasBitmap.CreateFromColors(device, colors, width, height))
            {
                byte[] currentByte = b.GetPixelBytes();
                currentByte.CopyTo(wb.PixelBuffer);
                wb.Invalidate();
                image.Source = wb;
                b.Dispose();
            }
        }

        /// <summary>
        /// 初始化图片
        /// </summary>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="image"></param>
        /// <param name="wb"></param>
        public static void InitialImage(CanvasBitmap bitmap, Image image)
        {
            var wb = new WriteableBitmap((int)bitmap.Size.Width, (int)bitmap.Size.Height);
            var bytes = bitmap.GetPixelBytes();
            bytes.CopyTo(wb.PixelBuffer);
            wb.Invalidate();
            image.Source = wb;
        }

        /// <summary>
        /// 二次插值
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static Color BiLinear2(double x, double y, Color[] colors, int width, int height)
        {
            int i = (int)Math.Floor(x);
            int j = (int)Math.Floor(y);
            double u = x - i;
            double v = y - j;

            int lx = i - 1 < 0 ? 0 : i - 1;
            int rx = i + 1 > width - 1 ? width - 1 : i + 1;

            int ty = j - 1 < 0 ? 0 : j - 1;
            int by = j + 1 < height - 1 ? height - 1 : j + 1;


            if (i >= width - 3)
            {
                i = width - 3;
            }

            if (j >= height - 3)
            {
                //Debug.WriteLine(" x:"+i+" y:"+  j + "");
                j = height - 3;
            }
            Color color = colors[(int)(i * height + j)];
            Color point0 = colors[i + width * j];
            Color point1 = colors[lx + ty * width];
            Color point2 = colors[rx + ty * width];
            Color point3 = colors[lx + by * width];
            int r, g, b;
            r = (int)((1 - u) * (1 - v) * point0.R + (1 - u) * v * point1.R + u * (1 - v) * point2.R + u * v * point3.R);
            g = (int)((1 - u) * (1 - v) * point0.G + (1 - u) * v * point1.G + u * (1 - v) * point2.G + u * v * point3.G);
            b = (int)((1 - u) * (1 - v) * point0.B + (1 - u) * v * point1.B + u * (1 - v) * point2.B + u * v * point3.B);

            r = r < 0 ? 0 : r;
            g = g < 0 ? 0 : g;
            b = b < 0 ? 0 : b;
            r = r > 255 ? 255 : r;
            g = g > 255 ? 255 : g;
            b = b > 255 ? 255 : b;

            return Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
        }

        //三次卷积插值
        public static Color Convolution(double x, double y, Color[] colors, int width, int height)
        {
            int i = (int)Math.Floor(x);
            int j = (int)Math.Floor(y);
            double u = x - i;
            double v = y - j;
            double[] A = new double[4] { S(u + 1), S(u), S(u - 1), S(u - 2) };
            Color[,] B = new Color[4, 4];
            double[] C = new double[4] { S(v + 1), S(v), S(v - 1), S(v - 2) };
            double[] temp = new double[4];
            double r = 0.0, g = 0.0, b = 0.0;
            int p, q;
            int Height = (int)width;
            int Width = (int)height;

            for (p = 0; p < 4; p++)
            {

                for (q = 0; q < 4; q++)
                {

                    int index = 0;
                    if (i + p - 1 >= 0 && i + p - 1 < Width && j + q - 1 >= 0 && j + q - 1 < Height)
                    {
                        index = (i + p - 1) + (j + q - 1) * width;
                        B[p, q] = colors[index];
                    }



                    else if ((i + p - 1 < 0) && (j + q - 1 >= 0) && (j + q - 1 < Height))
                    {
                        index = 0 + (j + q - 1) * width;

                        B[p, q] = colors[index];
                    }


                    else if ((i + p - 1 < 0) && (j + q - 1 < 0))
                    {
                        index = 0;
                        B[p, q] = colors[index];
                    }


                    else if ((i + p - 1 < 0) && (j + q - 1 >= Height))
                    {
                        index = 0 + (height - 1) * width;

                        B[p, q] = colors[index];
                    }


                    else if ((i + p - 1 >= 0) && (i + p - 1 < Width) && (j + q - 1 < 0))
                    {
                        index = (i + p - 1);

                        B[p, q] = colors[index];
                    }


                    else if ((i + p - 1 >= 0) && (i + p - 1 < Width) && (j + q - 1 >= Height))
                    {
                        index = (i + p - 1) + (height - 1) * width;

                        B[p, q] = colors[index];
                    }


                    else if ((i + p - 1 >= Width) && (j + q - 1 >= 0) && (j + q - 1 < Height))
                    {
                        index = (Width - 1) + (j + q - 1) * width;

                        B[p, q] = colors[index];
                    }


                    else if ((i + p - 1 >= Width) && (j + q - 1 < 0))
                    {
                        index = (Width - 1);

                        B[p, q] = colors[index];
                    }


                    else
                    {
                        index = (Width - 1) + (height - 1) * width;

                        B[p, q] = colors[index];
                    }

                }
            }

            //求r
            for (p = 0; p < 4; p++)                             //矩阵temp=A*B
            {
                temp[p] = 0;
                for (q = 0; q < 4; q++)
                    temp[p] += A[q] * B[q, p].R;
            }
            for (p = 0; p < 4; p++)                             //r=temp*C
                r += temp[p] * C[p];

            //求g
            for (p = 0; p < 4; p++)                             //矩阵temp=A*B
            {
                temp[p] = 0;
                for (q = 0; q < 4; q++)
                    temp[p] += A[q] * B[q, p].G;
            }
            for (p = 0; p < 4; p++)                             //g=temp*C
                g += temp[p] * C[p];

            //求b
            for (p = 0; p < 4; p++)                             //矩阵temp=A*B
            {
                temp[p] = 0;
                for (q = 0; q < 4; q++)
                    temp[p] += A[q] * B[q, p].B;
            }
            for (p = 0; p < 4; p++)                             //b=temp*C
                b += temp[p] * C[p];

            if (r > 255) r = 255;
            if (g > 255) g = 255;
            if (b > 255) b = 255;
            if (r < 0) r = 0;
            if (g < 0) g = 0;
            if (b < 0) b = 0;

            return (Color.FromArgb(255, (byte)r, (byte)g, (byte)b));
        }

        public static double S(double x)
        {
            if (Math.Abs(x) < 1)
                return 1 - 2 * Math.Pow(Math.Abs(x), 2) + Math.Pow(Math.Abs(x), 3);
            else if (Math.Abs(x) < 2)
                return 4 - 8 * Math.Abs(x) + 5 * Math.Pow(Math.Abs(x), 2) - Math.Pow(Math.Abs(x), 3);
            else return 0;
        }


        /// <summary>
        /// 二次插值
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static Color BiLinear(double x, double y, Color[] colors, int width, int height)
        {
            int i = (int)Math.Floor(x);
            int j = (int)Math.Floor(y);
            double u = x - i;
            double v = y - j;

            i = Math.Min(Math.Max(i, 0), width - 1);
            j = Math.Min(Math.Max(j, 0), height - 1);


            int rx = i + 1 > width - 1 ? width - 1 : i + 1;
            int by = j + 1 > height - 1 ? height - 1 : j + 1;




            Color point0 = colors[i + width * j];
            Color point1 = colors[i + width * (by)];
            Color point2 = colors[rx + width * j];
            Color point3 = colors[rx + width * by];
            int r, g, b;
            r = (int)((1 - u) * (1 - v) * point0.R + (1 - u) * v * point1.R + u * (1 - v) * point2.R + u * v * point3.R);
            g = (int)((1 - u) * (1 - v) * point0.G + (1 - u) * v * point1.G + u * (1 - v) * point2.G + u * v * point3.G);
            b = (int)((1 - u) * (1 - v) * point0.B + (1 - u) * v * point1.B + u * (1 - v) * point2.B + u * v * point3.B);

            r = r < 0 ? 0 : r;
            g = g < 0 ? 0 : g;
            b = b < 0 ? 0 : b;
            r = r > 255 ? 255 : r;
            g = g > 255 ? 255 : g;
            b = b > 255 ? 255 : b;

            return Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
        }

        /// <summary>
        /// 二次插值
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="colors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static Color BiLinear(int x, int y, double u1, double v1, Color[] colors, int width, int height)
        {
            int i = x;
            int j = y;
            double u = u1;
            double v = v1;

            Color color = colors[(int)(i * height + j)];


            if (j >= height - 1)
            {
                //Debug.WriteLine(" x:"+i+" y:"+  j + "");
                j = height - 2;
            }

            Color point0 = colors[i + width * j];
            Color point1 = colors[i + width * (j + 1)];
            Color point2 = colors[i + 1 + width * j];
            Color point3 = colors[(i + 1) + width * (j + 1)];
            int r, g, b;
            r = (int)((1 - u) * (1 - v) * point0.R + (1 - u) * v * point1.R + u * (1 - v) * point2.R + u * v * point3.R);
            g = (int)((1 - u) * (1 - v) * point0.G + (1 - u) * v * point1.G + u * (1 - v) * point2.G + u * v * point3.G);
            b = (int)((1 - u) * (1 - v) * point0.B + (1 - u) * v * point1.B + u * (1 - v) * point2.B + u * v * point3.B);

            r = r < 0 ? 0 : r;
            g = g < 0 ? 0 : g;
            b = b < 0 ? 0 : b;
            r = r > 255 ? 255 : r;
            g = g > 255 ? 255 : g;
            b = b > 255 ? 255 : b;

            return Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
        }


        public static double Map(double source, double rangel, double ranger, double targetl, double targetr)
        {

            double ran = ranger - rangel;






            return 0;

        }

        public static Color Smooth(int x, int y, Color[] colors, int width, int height)
        {

            int rr = 1;


            int sx = x - rr < 0 ? 0 : x - rr;
            int ex = x + rr > width - 1 ? width - 1 : x + rr;

            int sy = y - rr < 0 ? 0 : y - rr;
            int ey = y + rr > height - 1 ? height - 1 : y + rr;


            int r = 0, g = 0, b = 0;

            int count = 0;
            Color color = new Color();

            for (int xx = sx; xx <= ex; xx++)
            {
                for (int yy = sy; yy <= ey; yy++)
                {
                    Color item = colors[xx + yy * width];

                    r += item.R;
                    g += item.G;
                    b += item.B;

                    count++;
                }
            }

            color.R = (byte)(r / count);
            color.G = (byte)(g / count);
            color.B = (byte)(b / count);
            color.A = 255;
            return color;
        }


        public static Hsv RgbToHsv(Color c)
        {
            int R, G, B;
            R = c.R;
            G = c.G;
            B = c.B;

            double V, S, H = 0;

            double max = Math.Max(R, Math.Max(G, B));
            double min = Math.Min(R, Math.Min(G, B));

            var dalte = max - min;

            V = max / 255;

            S = dalte == 0 ? 0 : dalte / max;

            if (R == max) H = (G - B) / (max - min) * 60;
            if (G == max) H = 120 + (B - R) / (max - min) * 60;
            if (B == max) H = 240 + (R - G) / (max - min) * 60;
            if (dalte == 0) H = 0;
            if (H < 0)
                H = H + 360;


            Hsv hsv = new Hsv() { H = (int)H, S = S * 100, V = V * 100 };

            return hsv;
        }


        public static Color HsvToRgb(Hsv hsv)
        {


            double s = hsv.S / 100;
            double v = hsv.V / 100;
            double h = hsv.H;


            double R = 0, G = 0, B = 0;

            if (s == 0)
                R = G = B = v;
            else
                h /= 60;
            int i = (int)(h);
            double f = h - i;
            double a = v * (1 - s);
            double b = v * (1 - s * f);
            double c = v * (1 - s * (1 - f));


            switch (i)
            {
                case 0:
                case 6:
                    R = v; G = c; B = a;
                    break;
                case 1:
                    R = b; G = v; B = a;
                    break;
                case 2:
                    R = a; G = v; B = c;
                    break;
                case 3:
                    R = a; G = b; B = v;
                    break;
                case 4:
                    R = c; G = a; B = v;
                    break;
                case 5:
                    R = v; G = a; B = b;
                    break;
            }

            R *= 255;
            G *= 255;
            B *= 255;
            Color color = Color.FromArgb(255, (byte)R, (byte)G, (byte)B);
            return color;
        }


        public static double CalculateAngle(Vector2 center, Vector2 offset)
        {

            double a = offset.X - center.X;
            double b = offset.Y - center.Y;
            double pi = Math.PI;
            double dis = Math.Sqrt(a * a + b * b);
            double degree = 0;

            double mysin = (b / dis);
            var value = Math.Asin(mysin) / pi * 180;
            if (offset.X < center.X && offset.Y <= center.Y)
            {

                degree = 270 - value;
            }
            else if (offset.X > center.X && offset.Y < center.Y)
            {
                degree = 90 + value;
            }
            else if (offset.X <= center.X && offset.Y >= center.Y)
            {
                degree = 270 - value;
            }
            else
            {
                degree = 90 + value;
            }

            return degree;

        }

        public static Point AngleToPoint(Vector2 center, double angle, double radius)
        {
            double x = center.X + Math.Cos(angle + 90) * radius * Math.PI / 180;
            double y = center.Y + Math.Sin(angle + 9) * radius * Math.PI / 180;

            return new Point(x, y);

        }


        /// <summary>
        /// 就进填充颜色
        /// </summary>
        /// <param name="tempColors"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static Color[] RencentFillColor(Color[] tempColors, double width, double height)
        {
            Color[] cacheColor = new Color[tempColors.Length];
            tempColors.CopyTo(cacheColor, 0);
            int taskLength = 12;

            int mw = (int)width / (int)taskLength;
            int mh = (int)height;
            int pw = 0;
            int ph = 0;

            List<IAsyncAction> list = new List<IAsyncAction>();
            for (int i = 1; i <= taskLength; i++)
            {

                int sx = pw;
                int sy = ph;

                int ex = mw * i;
                int ey = mh;

                if (i == taskLength && width % taskLength != 0)
                {
                    ex = (int)width;
                }


                list.Add(Windows.System.Threading.ThreadPool.RunAsync(p =>
                {

                    FillColor(sx, sy, ex, ey, (int)width, (int)height, cacheColor, tempColors);

                }));

                pw = mw * i;
            }
            Task.WaitAll(list.Select(temp => temp.AsTask()).ToArray());
            return tempColors;
        }

        public static void FillColor(int sx, int sy, int ex, int ey, int width, int height, Color[] cacheColor, Color[] tempColors)
        {
            for (int x = sx; x < (int)ex; x++)
            {
                for (int y = sy; y < (int)ey; y++)
                {
                    try
                    {

                        int cx = Math.Min(Math.Max(x, 0), (int)width - 1);
                        int cy = Math.Min(Math.Max(y, 0), (int)height - 1);


                        int index = cx + cy * ((int)width);
                        var item = cacheColor[index];

                        if (item.A == 0)
                        {
                            int lx = x - 1 < 0 ? 0 : x - 1;
                            int rx = x + 1 > (int)width - 1 ? (int)width - 1 : x + 1;

                            int ty = y - 1 < 0 ? 0 : y - 1;
                            int by = y + 1 > (int)height - 1 ? (int)height - 1 : y + 1;


                            bool quyerColor = false;

                            Color tc = cacheColor[cx + ty * (int)width];
                            Color bc = cacheColor[cx + by * (int)width];
                            Color lc = cacheColor[lx + y * (int)width];
                            Color rc = cacheColor[rx + y * (int)width];

                            if (tc.A + bc.A + lc.A + rc.A == 0)
                                continue;
                            for (int xx = lx; xx < rx; xx++)
                            {
                                if (quyerColor)
                                {
                                    break;
                                }

                                for (int yy = ty; yy < by; yy++)
                                {

                                    int ci = xx + yy * ((int)width);
                                    Color color = cacheColor[ci];
                                    if (color.A != 0)
                                    {
                                        tempColors[index] = color;
                                        quyerColor = true;
                                        break;

                                    }
                                }
                            }





                        }
                    }
                    catch
                    {
                        int count = ex + ey;
                        int cx = Math.Min(Math.Max(x, 0), (int)width - 1);
                        int cy = Math.Min(Math.Max(y, 0), (int)height - 1);
                    }
                }
            }
        }
        public static void DrawGridGraphics(CanvasDrawingSession draw, int size = 100)
        {
            var target = new CanvasRenderTarget(draw, new Windows.Foundation.Size(size * 2, size * 2));
            using (var ds = target.CreateDrawingSession())
            {
                for (int x = 0; x < 2; x++)
                {
                    for (int y = 0; y < 2; y++)
                    {
                        Color color = (x + y) % 2 == 0 ? Colors.White : Color.FromArgb(255, 219, 219, 219);
                        ds.FillRectangle(new Rect(x * size, y * size, size, size), color);
                    }
                }
            }
            var gridTargetEffect = new BorderEffect()
            {
                Source = target,
                ExtendY = CanvasEdgeBehavior.Wrap,
                ExtendX = CanvasEdgeBehavior.Wrap,
            };
            draw.DrawImage(gridTargetEffect);
        }

        public static Transform2DEffect CalcutateImageCenteredTransform(double cWidth, double cHeight, double iWidth, double iHeight)
        {
            var mat = CalcutateImageCenteredMat(cWidth, cHeight, iWidth, iHeight);
            return new Transform2DEffect() { TransformMatrix = mat };
        }

        public static Transform2DEffect CalcutateImageCenteredTransform(Windows.Foundation.Size cSize, Windows.Foundation.Size iSize)
        {
            return CalcutateImageCenteredTransform(cSize.Width, cSize.Height, iSize.Width, iSize.Height);
        }

        public static Matrix3x2 CalcutateImageCenteredMat(Windows.Foundation.Size cSize, Windows.Foundation.Size iSize)
        {
            return CalcutateImageCenteredMat(cSize.Width, cSize.Height, iSize.Width, iSize.Height);
        }
        public static Matrix3x2 CalcutateImageCenteredMat(double cWidth, double cHeight, double iWidth, double iHeight)
        {
            float f = (float)Math.Min(cWidth / iWidth, cHeight / iHeight);
            float ox = (float)(cWidth - iWidth * f) / 2;
            float oy = (float)(cHeight - iHeight * f) / 2;
            Matrix3x2 matrix3X2 = Matrix3x2.CreateScale(f) * Matrix3x2.CreateTranslation(ox, oy);
            return matrix3X2;
        }



        /// <summary>
        /// 获取模板里面的指定类型和名字的控件控件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="element"></param>
        /// <returns></returns>
        public static T FindTemplateControl<T>(DependencyObject element, string name) where T : DependencyObject
        {
            int content = VisualTreeHelper.GetChildrenCount(element);

            for (int i = 0; i < content; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(element, i);

                var work = child as FrameworkElement;

                if (child != null && child is T && work.Name == name)
                {
                    return (T)child;
                }
                else
                {
                    T childOfChild = FindTemplateControl<T>(child, name);
                    if (childOfChild != null)
                    {
                        return childOfChild;
                    }
                }
            }
            return null;
        }


        public static async Task<byte[]> LoadShaderCode(string path)
        {
            StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(path));
            if (file == null)
                return null;
            var buffer = await FileIO.ReadBufferAsync(file);
            return buffer.ToArray();
        }

        public static Vector3 ToVector3(this Color color)
        {
            return new Vector3(color.R, color.G, color.B);
        }

        public static Vector3 ToVector3Normal(this Color color)
        {
            return new Vector3(color.R / 255f, color.G / 255f, color.B / 255);
        }

        public static Vector4 ToVector4(this Color color)
        {
            return new Vector4(color.R, color.G, color.B, color.A);

        }

        public static Vector4 ToVector4Normal(this Color color)
        {
            return new Vector4(color.R / 255f, color.G / 255f, color.B / 255, color.A / 255);
        }

        public static Color ToColor(this Vector2 vectorUnit)
        {
            return new Color
            {
                A = 255,
                R = (byte)(127 - 127 * vectorUnit.X),
                G = (byte)(127 - 127 * vectorUnit.Y),
                B = 255,
            };
        }
    }


    public class Hsv : INotifyPropertyChanged
    {



        private double _h;

        /// <summary>
        /// 色相 0~360
        /// </summary>
        public double H
        {
            get { return _h; }
            set
            {
                _h = value;
                OnPropertyChanged();
            }
        }

        private double _s;

        /// <summary>
        /// 亮度 0~100
        /// </summary>
        public double S
        {
            get { return _s; }
            set
            {
                _s = value;
                OnPropertyChanged();
            }
        }

        private double _v;

        /// <summary>
        /// 饱和度 0~100
        /// </summary>
        public double V
        {
            get { return _v; }
            set
            {
                _v = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// 将当前hsv转换成颜色返回
        /// </summary>
        public Color HsvToRgb()
        {
            double s = this.S / 100;
            double v = this.V / 100;
            double h = this.H;


            double R = 0, G = 0, B = 0;

            if (s == 0)
                R = G = B = v;
            else
                h /= 60;
            int i = (int)(h);
            double f = h - i;
            double a = v * (1 - s);
            double b = v * (1 - s * f);
            double c = v * (1 - s * (1 - f));


            switch (i)
            {
                case 0:
                case 6:
                    R = v; G = c; B = a;
                    break;
                case 1:
                    R = b; G = v; B = a;
                    break;
                case 2:
                    R = a; G = v; B = c;
                    break;
                case 3:
                    R = a; G = b; B = v;
                    break;
                case 4:
                    R = c; G = a; B = v;
                    break;
                case 5:
                    R = v; G = a; B = b;
                    break;
            }

            R *= 255;
            G *= 255;
            B *= 255;
            Color color = Color.FromArgb(255, (byte)R, (byte)G, (byte)B);

            return color;
        }

    }
}
